require 'openssl'

# wrapper over OpenSSL::Cipher::Cipher
module Cipher
  class Base
    attr_reader :cipher
    
    DEFAULT_IV = 0.chr * 8
    DEFAULT_PADDING = 0
    
    def initialize(cipher_string, iv = DEFAULT_IV, padding = DEFAULT_PADDING)
      @cipher = OpenSSL::Cipher::Cipher.new(cipher_string)
      self.iv = iv
      self.padding = padding
    end
    
    def encrypt(plaintext, key)
      @cipher.encrypt
      self.key = key
      @cipher.update(plaintext) + @cipher.final
    end
    
    def decrypt(ciphertext, key)
      @cipher.decrypt
      self.key = key
      @cipher.update(ciphertext) + @cipher.final
    end
    
    def iv
      @cipher.iv
    end

    def iv=(input)
      input = input.rjust(self.iv_length, 0.chr)
      if input.length != self.iv_length
        raise "bad iv length: #{input.length}; should be #{iv_length}"
      end
      @cipher.iv = input
    end

    def iv_length
      @cipher.iv_len
    end

    def key=(input)
      input = input.rjust(self.key_length, 0.chr)
      if input.length != self.key_length
        raise "bad key length: #{input.length}; should be #{key_length}"
      end
      @cipher.key = input
    end

    def key_length
      @cipher.key_len
    end

    def padding
      @cipher.padding
    end

    def padding=(input)
      @cipher.padding = input
    end

    def block_size
      @cipher.block_size
    end
  end

  class DES < Base
    def initialize
      super('des')
    end
  end
end

